#include "pub_sub/pub_sub_infos.h"
#include <algorithm>
#include <unistd.h>

// ==================== SubInfosManager 实现 ====================

bool SubInfosManager::registerSubscriber(const std::string& topic_name, const SubscriberInfo& info) {
    std::lock_guard<std::mutex> lock(sub_infos_mutex_);
    
    auto it = sub_infos_.find(topic_name);
    if (it != sub_infos_.end()) {
        if (!it->second.is_active) {
            it->second = info;
            return true;
        }
        return false;
    }
    
    sub_infos_[topic_name] = info;
    return true;
}

bool SubInfosManager::unregisterSubscriber(const std::string& topic_name) {
    std::lock_guard<std::mutex> lock(sub_infos_mutex_);
    
    auto it = sub_infos_.find(topic_name);
    if (it != sub_infos_.end()) {
        if (it->second.eventfd >= 0) {
            close(it->second.eventfd);
        }
        
        it->second.is_active = false;
        sub_infos_.erase(it);
        return true;
    }
    
    return false;
}

SubscriberInfo* SubInfosManager::getSubscriberInfo(const std::string& topic_name) {
    std::lock_guard<std::mutex> lock(sub_infos_mutex_);
    
    auto it = sub_infos_.find(topic_name);
    if (it != sub_infos_.end() && it->second.is_active) {
        return &it->second;
    }
    
    return nullptr;
}

bool SubInfosManager::hasSubscriber(const std::string& topic_name) const {
    std::lock_guard<std::mutex> lock(sub_infos_mutex_);
    
    auto it = sub_infos_.find(topic_name);
    return it != sub_infos_.end() && it->second.is_active;
}

std::vector<std::string> SubInfosManager::getActiveTopics() const {
    std::lock_guard<std::mutex> lock(sub_infos_mutex_);
    
    std::vector<std::string> active_topics;
    for (const auto& pair : sub_infos_) {
        if (pair.second.is_active) {
            active_topics.push_back(pair.first);
        }
    }
    
    return active_topics;
}

void SubInfosManager::cleanup() {
    std::lock_guard<std::mutex> lock(sub_infos_mutex_);
    
    auto it = sub_infos_.begin();
    while (it != sub_infos_.end()) {
        if (!it->second.is_active) {
            if (it->second.eventfd >= 0) {
                close(it->second.eventfd);
            }
            it = sub_infos_.erase(it);
        } else {
            ++it;
        }
    }
}

std::vector<SubscriberInfo> SubInfosManager::getSubscriberInfos() const {
    std::lock_guard<std::mutex> lock(sub_infos_mutex_);
    std::vector<SubscriberInfo> subscriber_infos;
    for (const auto& sub_info : sub_infos_) {
        subscriber_infos.push_back(sub_info.second);
    }
    return subscriber_infos;
}

// ==================== PubInfosManager 实现 ====================

bool PubInfosManager::registerPublisher(const std::string& topic_name, const PublisherInfo& info) {
    std::lock_guard<std::mutex> lock(pub_infos_mutex_);
    
    auto it = pub_infos_.find(topic_name);
    if (it != pub_infos_.end()) {
        if (!it->second.is_active) {
            it->second = info;
            return true;
        }
        return false;
    }
    
    pub_infos_[topic_name] = info;
    return true;
}

bool PubInfosManager::unregisterPublisher(const std::string& topic_name) {
    std::lock_guard<std::mutex> lock(pub_infos_mutex_);
    
    auto it = pub_infos_.find(topic_name);
    if (it != pub_infos_.end()) {
        it->second.is_active = false;
        // pub_infos_.erase(it);
        return true;
    }
    
    return false;
}

PublisherInfo* PubInfosManager::getPublisherInfo(const std::string& topic_name) {
    std::lock_guard<std::mutex> lock(pub_infos_mutex_);
    
    auto it = pub_infos_.find(topic_name);
    if (it != pub_infos_.end() && it->second.is_active) {
        return &it->second;
    }
    
    return nullptr;
}

bool PubInfosManager::hasPublisher(const std::string& topic_name) const {
    std::lock_guard<std::mutex> lock(pub_infos_mutex_);
    
    auto it = pub_infos_.find(topic_name);
    return it != pub_infos_.end() && it->second.is_active;
}

std::vector<std::string> PubInfosManager::getActiveTopics() const {
    std::lock_guard<std::mutex> lock(pub_infos_mutex_);
    
    std::vector<std::string> active_topics;
    for (const auto& pair : pub_infos_) {
        if (pair.second.is_active) {
            active_topics.push_back(pair.first);
        }
    }
    
    return active_topics;
}

void PubInfosManager::cleanup() {
    std::lock_guard<std::mutex> lock(pub_infos_mutex_);
    
    auto it = pub_infos_.begin();
    while (it != pub_infos_.end()) {
        if (!it->second.is_active) {
            it = pub_infos_.erase(it);
        } else {
            ++it;
        }
    }
}

std::vector<PublisherInfo> PubInfosManager::getPublisherInfos() const {
    std::lock_guard<std::mutex> lock(pub_infos_mutex_);
    std::vector<PublisherInfo> publisher_infos;
    for (const auto& pub_info : pub_infos_) {
        publisher_infos.push_back(pub_info.second);
    }
    return publisher_infos;
}

// function implementation

std::string pub_sub_infos_to_string() {
    std::stringstream ss;
    ss << "Publishers: " << std::endl;
    for (const auto& pub_info : PubInfosManager::getInstance().getPublisherInfos()) {
        ss << pub_info.topic_name << " " << pub_info.is_active << std::endl;
    }
    return ss.str();
}